论软件的可靠性设计
摘要
2019年11月,我所在的软件公司承接了某保险集团下健康险服务实施管理系统的开发工作,本人有幸参与该项目,并担任系统架构师职务,主要负责软件架构设计和可靠性设计的工作。该项目是基于集团内网,为全国各省市地区分支机构的健康险专员提供7*24小时的不间断服务。笔者以该项目为例,先简单介绍几种目前比较主流的软件可靠性设计技术,然后讨论可靠性设计技术在项目中的具体应用。项目组结合软件可靠性设计与应用的原则,结合此前类似系统的设计经验,决定对软件系统采用软件容错的N版本程序设计技术,对消息通讯、分层架构模块进行负载均衡设计。经过项目组九个多月的努力,本系统已顺利开发完成,于2020年7月投入生产环境使用。自上线以来未出现重大故障,取得客户和公司领导的一致好评。
正文
近年来,随着互联网行业的迅猛发展,公司业务的不断扩张,需求的快速变化以及用户量的持续增加,传统的业务系统已无法满足这样迅猛的业务数据量。在2019年11月,我所在的软件公司承接了某保险集团下健康险服务实施管理系统的开发工作,本人有幸参与该项目,并担任系统架构师职务,主要负责软件架构和可靠性设计的工作。笔者以该项目为例,先简单介绍几种目前比较主流的软件可靠性设计技术,然后讨论可靠性设计技术在项目中的具体应用。项目组结合软件可靠性设计与应用的原则,结合此前类似系统的设计经验,决定对软件系统采用软件容错的N版本程序设计技术,对消息通讯、分层架构模块进行负载均衡设计。
项目概述
随着信息技术的蓬勃发展,传统业务系统已无法满足日益增长的业务工作量,对传统系统进行升级改造迫在眉睫。健康服务实施管理系统(Health Service Implementation Management System HSIMS),为企业健康险工作人员提供实时、高效、方便的线上办公服务,如此便利的2B业务系统间接的为健康险消费群体提供了更快更好的产品使用体验。HSIMS系统的建设,充分表现了健康险产品的整个生命周期,系统划分为产品管理、服务管理、协议管理、健康卡管理、供应商管理、服务实施管理、服务反馈管理等多个业务模块。在实际使用时,由健康险专员全程操作,根据岗位职能的不同各自负责不同的业务模块,从而达到高效稳健的业务协作,促进企业的进一步发展。限于篇幅,在此我们不再详细介绍各个模块的具体功能。
HSIMS稳定可靠的运行也是作为一项重要的验收指标。下面,我将首先介绍几种目前比较主流的软件可靠性设计技术,然后详细介绍HSIMS的分析和设计过程中所采用的可靠性设计技术及其原因。
可靠性设计技术
一般来说,被认可的且具有应用前景的软件可靠性设计技术主要有容错设计、检错设计和降低复杂度设计等技术。其中常用的软件容错技术主要有恢复块设计、N版本程序设计和冗余设计三种方法,主要适用于软件失效后果特别严重的场合,恢复块设计就是选择一组操作作为容错设计单元,从而把普通的程序块变为恢复块。一个恢复块中包含有若干功能相同、设计差异的程序块,每一时刻有一个程序块处于运行状态,一旦某程序块出现故障,则用备份程序块予以替换。N版本程序设计的核心是通过设计出多个模块或不同版本,对于相同初始条件和相同输入的操作结果进行多数表决(防止因其中某一软件模块/版本的故障而提供了错误的服务,以实现软件容错)。冗余设计的思路来源于硬件系统,但有所不同。软件冗余设计技术是采用多种不同路径、不同算法或不同实现方法的模块或系统作为备份,在出现故障时进行替换,维持系统的正常运行。;检错设计主要应用于无需在线容错的地方或不能采用冗余设计技术的部分;降低复杂度设计的思想就是在保证实现软件功能的基础上,简化软件结构,缩短程序代码长度,优化软件数据流向,降低软件复杂度,从而提高软件可靠性。除此之外,还有故障树分析(FTA)、失效模式与效应分析(FMEA)等硬件可靠性技术也应用到了软件可靠性设计领域之中。
影响可靠性要点
项目启动后,在架构设计工作的开始阶段,我们便意识到软件的可靠性设计对项目有着重要的影响。由于保险系统的复杂性与特殊性,对软件可靠性有着较高的要求,要提高软件产品的可靠性指标,首先要分析影响软件产品可靠性的因素。一般来说影响产品可靠性的原因有如下几点:
1、运行环境,软件可靠性定义是相对于运行环境而言的,同样的软件在不同的运行环境下其可靠性是不一样的。不同的用户,操作习惯不同,会影响软件的可靠性。软件的可靠性是软件缺陷和用户的可预测性的一个复杂函数。
2、软件规模,也就是软件的大小。一个只有几百行代码的软件和一个几千万行代码的软件是不能相提并论的。
3、软件内部结构,结构对软件可靠性的影响主要是软件的复杂程度,一般来说,结构越复杂的软件,所包含的软件缺陷数就可能越多。在进行软件设计时就要有意识地采用各种降低复杂度的架构策略,如模块化设计,分层设计等等。分而治之的方法是最好的降低复杂度的方法。
4、软件的开发环境和开发方法,软件工程表明,软件的开发方法对软件的可靠性有显著地影响。例如,与非结构化开发方法相对,结构化方法可以明显减少软件的缺陷数。
5、软件的可靠性投入,软件在生命周期中的可靠性投入包括可靠性设计、可靠性测试、可靠性管理和可靠性评价等方面投入的人力、资源、资金和时间等。
可靠性设计应用
笔者根据系统本身的特点,结合以上五个影响软件可靠性的因素,对系统做了以下几点可靠性设计:
- 运行环境方面,使用了微服务组件配合实现可靠性,其中包括:
- eureka注册中心:通过定时的心跳信息号推送,让注册中心管理各个微服务的健康状况,保证服务间的调用都是基于良好的服务状态。
- Apollo配置中心:全局统一配置,提供配置文件统一管理能力,实现各微服务的统一参数配置以及版本管理,大大降低了手动配置的不稳定性,提升系统可靠性。
- Zuul网关:通过使用网关进行请求的转发,对于请求失败或请求异常的情况及时记录日志,统一返回合适的响应报文。
- Hystrix熔断组件:当请求多次访问被异常阻塞时,系统会启用熔断机制,将该接口挂起修复,直到其恢复正常再次启用。
- Zipkin链路跟踪:提供服务调用和数据库调用的链路跟踪,一个请求可能需要调用很多个服务,而内部服务的调用复杂性,决定了问题难以定位。所以微服务架构中,必须实现分布式链路追踪,去跟进一个请求到底有哪些服务参与,参与的顺序又是怎样,从而达到每个请求的步骤清晰可见,出现问题时可以很快定位问题点,便于运维人员及时处理。
- 模块划分方面,在项目启动初期,我已经协调架构组和需求组慎重评估对于业务模块的划分,在保证业务划分的基础上也要考虑模块结构不能太复杂,对于业务繁重的模块要考虑部署多个服务实例或者拆分出公共部分简化模块。
- 定期培训,要求需求测试人员对于测试案例要有足够多的反向案例,开发人员在开发过程中可以更多的进行预防性开发,以提高各自功能的可靠性。
遇到的问题及解决方案
在项目推进的过程中,针对可靠性设计还遇到了比较严峻的问题。当集成测试和验收测试都通过后,按照流程顺利的搭建了生产试运行环境,其硬件配置、软件依赖版本均为最终的生产参数。试运行期间出现了严重的服务宕机情况,排查问题加问题修复共计耗时三个小时,最终问题点是因为试运行环境上的某个软件依赖冲突,导致整个服务启动失败。最后经过项目组内部讨论决定延期两周上线,在所有集成测试和验收测试环境完全仿照试运行的服务器配置进行集中的回归测试。两周时间内排查出其余问题点并全部解决。针对这种上线前因为环境问题导致的服务崩溃问题,项目组内部开会讨论分析原因,最终提出可以采用Docker的方式避免这样的问题,Docker可以实现虚拟机隔离应用环境的功能,并且开销比虚拟机小。这样可以很大程度解决环境移植的过程中服务可靠性的问题。
通过本次项目,对于软件可靠性设计有了更加深刻的经验,尤其在最后试运行期间出现的问题更是对我们项目组的一场挑战,相信经过这次项目的开发与实施,项目组内每位同事都受益匪浅。